package com.richard.library.bluetooth;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;

import com.richard.library.bluetooth.adapter.BleDeviceAdapter;
import com.richard.library.bluetooth.databinding.DialogSelectBleBinding;
import com.richard.library.bluetooth.dto.BleDevice;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <pre>
 * Description : 蓝牙设备选择
 * Author : Richard
 * Date : 2023/4/16 07:56
 * Changelog:
 * Version            Date            Author              Detail
 * ----------------------------------------------------------------------
 * 1.0         2023/4/16 07:56      xiejiao         new file.
 * </pre>
 */
public class SelectBleDialog extends AppCompatDialogFragment {

    private DialogSelectBleBinding binding;
    private BleDeviceAdapter adapter;
    private BluetoothManager bleManager;
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothLeScanner scanner;
    private boolean isScanning = false;//是否正在扫描
    private Callback callback;
    private boolean isExcludeUnknown;//是否排除未知蓝牙设备

    public static void startForResult(FragmentManager manager,boolean isExcludeUnknown, Callback callback) {
        SelectBleDialog dialog = new SelectBleDialog();
        dialog.isExcludeUnknown = isExcludeUnknown;
        dialog.setCallback(callback);
        dialog.show(manager, String.valueOf(System.currentTimeMillis()));
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = DialogSelectBleBinding.inflate(inflater);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        this.initData();
        this.bindListener();
    }

    @Override
    public void onStart() {
        super.onStart();
        if (getDialog() == null) {
            return;
        }
        Window window = getDialog().getWindow();
        if (window != null) {
            WindowManager.LayoutParams params = window.getAttributes();
            params.width = this.dp2px(320);
            params.height = this.dp2px(300);
            window.setAttributes(params);
        }
    }

    /**
     * 初始化数据
     */
    private void initData() {
        binding.rvView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
        adapter = new BleDeviceAdapter();
        binding.rvView.setAdapter(adapter);
        this.setDefaultAnimatorOpen(false);

        if (initBluetooth()) {
            if (isOpenBluetooth()) {
                if (scanner == null) {
                    scanner = bluetoothAdapter.getBluetoothLeScanner();
                }
                this.scanBluetooth();
            } else {
                this.openBluetooth();
            }
        }
    }

    /**
     * 设置是否开启默认动画
     */
    public void setDefaultAnimatorOpen(boolean isOpen) {
        RecyclerView.ItemAnimator itemAnimator = binding.rvView.getItemAnimator();
        if (itemAnimator != null) {
            itemAnimator.setAddDuration(isOpen ? 120 : 0);
            itemAnimator.setChangeDuration(isOpen ? 250 : 0);
            itemAnimator.setMoveDuration(isOpen ? 250 : 0);
            itemAnimator.setRemoveDuration(isOpen ? 120 : 0);
            ((SimpleItemAnimator) itemAnimator).setSupportsChangeAnimations(isOpen);
        }
    }

    /**
     * 事件监听绑定
     */
    private void bindListener() {
        binding.ivClose.setOnClickListener((v) -> {
            dismiss();
        });

        adapter.setCallback(device -> {
            dismiss();
            if (callback != null) {
                callback.onResultDevice(device);
            }
        });
    }

    @Override
    public void onDestroy() {
        this.stopScan();
        enableBluetooth.unregister();
        requestLocation.unregister();
        requestBluetoothConnect.unregister();
        requestBluetoothScan.unregister();
        super.onDestroy();
    }

    /**
     * 初始化蓝牙
     */
    private boolean initBluetooth() {
        bleManager = (BluetoothManager) getContext().getSystemService(Context.BLUETOOTH_SERVICE);
        if (bleManager == null) {
            this.updateStateUI(false, "该设备不支持蓝牙");
            return false;
        }

        bluetoothAdapter = bleManager.getAdapter();

        if (bluetoothAdapter == null) {
            this.updateStateUI(false, "该设备不支持蓝牙");
            return false;
        }

        return true;
    }

    /**
     * 打开蓝牙
     */
    private void openBluetooth() {
        //是Android12
        if (isAndroid12Above()) {
            //检查是否有BLUETOOTH_CONNECT权限
            if (hasPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
                //打开蓝牙
                enableBluetooth.launch(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
            } else {
                //请求权限
                requestBluetoothConnect.launch(Manifest.permission.BLUETOOTH_CONNECT);
            }
            return;
        }

        //不是Android12 直接打开蓝牙
        enableBluetooth.launch(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
    }

    /**
     * 扫描蓝牙设备
     */
    private void scanBluetooth() {
        if (isAndroid12Above()) {
            if (hasPermission(Manifest.permission.BLUETOOTH_SCAN)) {
                startScan();
            } else {
                //请求权限
                requestBluetoothScan.launch(Manifest.permission.BLUETOOTH_SCAN);
            }
        } else {
            if (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
                startScan();
            } else {
                requestLocation.launch(Manifest.permission.ACCESS_FINE_LOCATION);
            }
        }
    }

    /**
     * 开始扫描
     */
    private void startScan() {
        if (isScanning) {
            return;
        }
        if (isOpenBluetooth()) {
            this.loadPairedDevice();
            scanner.startScan(scanCallback);
        }
        isScanning = true;
        this.updateStateUI(true, "蓝牙扫描中");
    }

    /**
     * 停止扫描
     */
    private void stopScan() {
        if (!isScanning) {
            return;
        }
        if (isOpenBluetooth()) {
            scanner.stopScan(scanCallback);
        }
        isScanning = false;
        binding.contentLoading.setVisibility(View.GONE);
    }

    /**
     * 加载已配对的蓝牙设备列表
     */
    private void loadPairedDevice() {
        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() <= 0) {
            return;
        }

        List<BluetoothDevice> pairedDeviceList = new ArrayList<>(pairedDevices);
        List<BleDevice> data = new ArrayList<>();
        for (BluetoothDevice item : pairedDeviceList) {
            data.add(new BleDevice(item));
        }
        adapter.update(data);
    }

    //扫描结果回调
    private final ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            if(isExcludeUnknown){
                String name = result.getDevice().getAlias();
                if(TextUtils.isEmpty(name)){
                    name = result.getDevice().getName();
                }
                if(TextUtils.isEmpty(name)){
                    return;
                }
            }

            adapter.update(new BleDevice(result.getDevice(), result.getRssi()));
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            updateStateUI(false, String.format("扫描蓝牙中发生错误 errorCode: %s", errorCode));
        }
    };

    /**
     * 更新显示状态updateStateUI
     */
    private void updateStateUI(boolean isShowProgress, String msg) {
        binding.contentLoading.setVisibility(View.VISIBLE);
        binding.pbView.setVisibility(isShowProgress ? View.VISIBLE : View.GONE);
        binding.tvState.setText(msg);
    }

    /**
     * 验证蓝牙是否已经开启
     */
    private boolean isOpenBluetooth() {
        return bleManager != null && bluetoothAdapter != null && bluetoothAdapter.isEnabled();
    }

    /**
     * 验证是否拥有指定权限
     */
    private boolean hasPermission(String permission) {
        return ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 验证是否是android 12以上的版本
     */
    private boolean isAndroid12Above() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
    }

    private void showMsg(String msg) {
        Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
    }

    //打开蓝牙意图
    private final ActivityResultLauncher<Intent> enableBluetooth = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
        switch (result.getResultCode()) {
            case Activity.RESULT_OK:
                if (isOpenBluetooth()) {
                    if (scanner == null) {
                        scanner = bluetoothAdapter.getBluetoothLeScanner();
                    }
                    scanBluetooth();
                } else {
                    showMsg("蓝牙未打开");
                    dismiss();
                }
                break;
            case Activity.RESULT_CANCELED:
                dismiss();
                break;
        }
    });

    //请求定位权限意图
    private final ActivityResultLauncher<String> requestLocation = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
        if (result) {
            //扫描蓝牙
            startScan();
        } else {
            showMsg("当前Android系统需要定位权限才能扫描设备");
        }
    });

    //请求BLUETOOTH_CONNECT权限意图
    private final ActivityResultLauncher<String> requestBluetoothConnect = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
        if (result) {
            //打开蓝牙
            enableBluetooth.launch(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
        } else {
            showMsg("蓝牙连接权限未授权，无法打开蓝牙");
        }
    });


    //请求BLUETOOTH_SCAN权限意图
    private final ActivityResultLauncher<String> requestBluetoothScan = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
        if (result) {
            //进行扫描
            startScan();
        } else {
            showMsg("扫描蓝牙权限未授权，无法扫描蓝牙");
        }
    });

    /**
     * dp转px
     *
     * @param dpVal dp值
     */
    private int dp2px(float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics());
    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public interface Callback {

        void onResultDevice(BleDevice device);

    }
}
